/* $RCSFile: DBDataStore.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/DAL/DBDataStore.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:28  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Threading;
using System.Globalization;
using System.Diagnostics;
using System.Data;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Web.Configuration;
using System.Data.SqlClient;

using AddonNice.Configuration;
using AddonNice.Diagnostics;
using AddonNice.Settings.Cache;

namespace AddonNice.Settings
{
	/// <summary>
	/// All DatabaseDB access modules inherit from this class 
	/// </summary>
	public class DBDataStore
	{
        const string strConnection = "ADNCRM_Connection";

        /// <summary>
        /// Used only by GetVersion
        /// </summary>
        static public SqlConnection CreateStaticConnection()
        {
            return Config.DefSqlConnection;
        }

        /// <summary>
        /// We use one  connection for each transaction ( regardless of connection pool management )
        /// </summary>
        public virtual SqlConnection myConnection
        {
            get
            {
                object ob                                       =   HttpContext.Current.Items[strConnection];
                if ( ob == null || !(ob is SqlConnection) )
                {
                    SqlConnection myConnect                     =   Config.DefSqlConnection;
                    HttpContext.Current.Items[strConnection]    =   myConnect;
                    return myConnect;
                }
                return (SqlConnection)ob;
            }
        }

        /// <summary>
        /// Returns either existing connection if state not Open, either a new one free ok for openning
        /// Beware THIS IS A NEW CONNECTION EACH TIME, to use it, assign its value to a local var
        /// </summary>
        public virtual SqlConnection newConnection
        {
            get
            {
                SqlConnection theConnection =   myConnection;
                if ( theConnection.State == ConnectionState.Open )
                    theConnection           =   Config.DefSqlConnection;
                return theConnection;
            }
        }

        /// <summary>
        /// Encrypts the string using HashPasswordForStoringInConfigFile
        /// </summary>
        protected string Crypt(string str)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(str, "sha1");
        }
		
        /// <summary>
		/// This is the current thread LCID, takes first NeutralCulture from CurrentUICulture
		/// </summary>
		public int LCID
		{
			get
			{
				if ( Thread.CurrentThread.CurrentUICulture.IsNeutralCulture )
					return Thread.CurrentThread.CurrentUICulture.LCID;
				return Thread.CurrentThread.CurrentUICulture.Parent.LCID;
			}
		}

		/// <summary>
		/// From current thread, extracts the 2 letters ISO language id
		/// </summary>
		public string TwoLetterISOLanguageName
		{
			get
			{
				if ( Thread.CurrentThread.CurrentUICulture.IsNeutralCulture )
					return Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
				return Thread.CurrentThread.CurrentUICulture.Parent.TwoLetterISOLanguageName;
			}
		}

        /// <summary>
        /// Beware in db the 'xx-yy' code is replaced by 'XX_YY'
        /// </summary>
		public string CurrentUICultureName
		{
			get
			{
				return Thread.CurrentThread.CurrentUICulture.Name.Replace('-','_').ToUpper(CultureInfo.InvariantCulture);
			}
		}

		int	_DefLangID						=	int.MinValue;
		/// <summary>
		/// The LCID for the defaut culture specified in web.config with key DefaultLanguege
		/// </summary>
		public int DefLCID
		{
			get
			{
				if ( _DefLangID != int.MinValue )
					return _DefLangID;
			
				string langlist				=	Config.DefaultLanguage;
				char[] itemsSeparator		=   {';'};
				char[] keyValueSeparator	=   {'='};

				string[] nameValues			=	langlist.Split(itemsSeparator);
				string	nameValue			=	nameValues[0];
				string[] arrNameValue		=   nameValue.Split(keyValueSeparator);

				CultureInfo language		=	new CultureInfo(arrNameValue[0].Substring(0,2));
				_DefLangID					=	language.LCID;
				return _DefLangID;
			}
        }
        
        #region SqlCommand common parameters

        /// <summary>
        /// Add to sent sqlcommand 2 parameters necessary for globalized sproc: LCID , DefLCID
        /// </summary>
        public virtual void AddGlobalizeParameters(SqlCommand myCommand)
        {
			if ( DBTraceSwitch.Sw.TraceVerbose)
                Trace.WriteLine("[V]DBDataStore AddGlobalizeParameters Called.",DBTraceSwitch.Sw.Info);
			SqlParameter parameterLCID		=	new SqlParameter(StStr.ATLCID, SqlDbType.Int, 4);
			parameterLCID.Value				=	LCID;
			myCommand.Parameters.Add(parameterLCID);

            SqlParameter parameterDefLCID	=	new SqlParameter(StStr.ATDefLCID, SqlDbType.Int, 4);
			parameterDefLCID.Value			=	DefLCID;
			myCommand.Parameters.Add(parameterDefLCID);
        }

        /// <summary>
        /// Add to sent sqlcommand the StStr.ATPortalID
        /// </summary>
        public virtual SqlParameter AddPortalIDParameters(SqlCommand myCommand, int PortalID)
        {
            SqlParameter parameterPortalID  =   new SqlParameter(StStr.ATPortalID, SqlDbType.Int, 4);
            parameterPortalID.Value         =   PortalID;
            myCommand.Parameters.Add(parameterPortalID);
            return parameterPortalID;
        }

        /// <summary>
        /// Add to sent sqlcommand the StStr.PageID
        /// </summary>
        public virtual SqlParameter AddPageIDParameters(SqlCommand myCommand, int pageID)
        {
            SqlParameter parameterPageID        =   new SqlParameter(StStr.ATPageID, SqlDbType.Int, 4);
            parameterPageID.Value               =   pageID;
            myCommand.Parameters.Add(parameterPageID);
            return parameterPageID;
        }

        /// <summary>
        /// Add to sent sqlcommand the StStr.SitePageID
        /// </summary>
        public virtual SqlParameter AddSitePageIDParameters(SqlCommand myCommand, int pageID)
        {
            SqlParameter parameterPageID        =   new SqlParameter(StStr.ATSitePageID, SqlDbType.Int, 4);
            parameterPageID.Value               =   pageID;
            myCommand.Parameters.Add(parameterPageID);
            return parameterPageID;
        }

        /// <summary>
        /// Add to sent sqlcommand the StStr.ATModuleID
        /// </summary>
        public virtual SqlParameter AddModuleIDParameters(SqlCommand myCommand, int moduleID)
        {
            SqlParameter parameterModuleID = new SqlParameter(StStr.ATModuleID, SqlDbType.Int, 4);
            parameterModuleID.Value = moduleID;
            myCommand.Parameters.Add(parameterModuleID);
            return parameterModuleID;
        }

        /// <summary>
        /// Add to sent sqlcommand the StStr.ATItemID
        /// </summary>
        public virtual SqlParameter AddItemIDParameters(SqlCommand myCommand, int itemID)
        {
            SqlParameter parameterItemID		=	new SqlParameter(StStr.ATItemID, SqlDbType.Int, 4);
            parameterItemID.Value				=	itemID;
            myCommand.Parameters.Add(parameterItemID);
            return parameterItemID;
        }
        
        #endregion SqlCommand common parameters


        /// <summary>
		/// For all tables in the dataset changes the utc date values in local time before displaying the values
		/// </summary>
		public static DataSet CheckDataSetForDates(DataSet ds)
		{
			Type t	=	typeof(DateTime);
			DateTime MinValue	=	DateTime.MinValue.Date.AddDays(10);
			DateTime MaxValue	=	DateTime.MaxValue.Date.AddDays(-10);
			foreach(DataTable tb in ds.Tables )
			{
				if ( tb.Rows.Count == 0 )
					continue;
				bool found	=	 false;
				foreach (DataColumn c in tb.Columns)
				{
					if ( c.DataType == t )
					{
						found	=	true;
						break;
					}
				}
				if ( !found )
					continue;
				CheckDataTableForDates(tb);
			}
			return ds;
		}

		/// <summary>
		/// For this table changes the utc date values in local time before displaying the values
		/// </summary>
		public static DataTable CheckDataTableForDates(DataTable tb)
		{
			Type t = typeof(DateTime);
			DateTime MinValue = DateTime.MinValue.Date.AddDays(10);
			DateTime MaxValue = DateTime.MaxValue.Date.AddDays(-10);
			
			if (tb.Rows.Count == 0)
				return tb;
			bool found = false;
			foreach (DataColumn c in tb.Columns)
			{
				if (c.DataType == t)
				{
					found = true;
					break;
				}
			}
			if (!found)
				return tb;
			foreach (DataRow rw in tb.Rows)
			{
				foreach (DataColumn c in tb.Columns)
				{
					if (c.DataType == t)
					{
						if (rw[c.ColumnName] != null && rw[c.ColumnName] != System.DBNull.Value)
						{
							DateTime dt = (DateTime)rw[c.ColumnName];
							try
							{
								if (dt >= MinValue && dt <= MaxValue)
									rw[c.ColumnName] = dt.ToLocalTime();

							}
							catch (Exception exp)
							{
								if ( DBTraceSwitch.Sw.TraceError )
                                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"DBDataStore CheckDataTableForDates tb: {0} Date:{1} ex : {2}", tb.TableName, dt, exp),DBTraceSwitch.Sw.Info);
							}
						}
					}
				}
			}
			return tb;
		}

        public byte[] GetFromSqlDataReaderByChunks(SqlDataReader reader, int ordinal)
        {
            const int bufsz     =   100000;
            byte[] data         =   new byte[bufsz];

            MemoryStream ms     =   new MemoryStream();
            int index = 0;
            while (true)
            {
                long count      =   reader.GetBytes(ordinal, index, data, 0, bufsz);
                if (count == 0)
                    break;
                else
                {
                    index       =   index + (int)count;
                    ms.Write(data, 0, (int)count);
                }
            }
            byte[] buf = ms.ToArray();
            return buf;
        }


	}
}
			